package com.yunchao.bank.main.presentation.screen

import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import by.kirich1409.viewbindingdelegate.viewBinding
import com.seuic.scankey.IKeyEventCallback
import com.seuic.scankey.ScanKeyService
import com.yunchao.bank.R
import com.yunchao.bank.business.pesentation.screen.info.BusinessInfoFragment
import com.yunchao.bank.configure.presentation.screen.ConfigureActivity
import com.yunchao.bank.databinding.ActivityMainBinding
import com.yunchao.feature.base.presentation.activity.BaseActivity
import com.yunchao.feature.base.presentation.activity.BaseKeyEventFragment
import com.yunchao.feature.base.presentation.ext.hideLoadingDialog
import com.yunchao.feature.base.presentation.ext.navigateSafe
import com.yunchao.feature.base.presentation.ext.showLoadingDialog
import com.yunchao.feature.base.presentation.ext.showTipDialog
import com.yunchao.feature.base.presentation.ext.toast
import com.yunchao.feature.base.presentation.nav.NavManager
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import kotlin.getValue

internal class MainActivity : BaseActivity(R.layout.activity_main),
    NavController.OnDestinationChangedListener {

    private val binding: ActivityMainBinding by viewBinding()
    private val viewModel: MainViewModel by viewModel<MainViewModel>()

    private lateinit var appBarConfiguration: AppBarConfiguration
    private val navManager: NavManager by inject()

    private val menuProvider: MenuProvider by lazy {
        object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menuInflater.inflate(R.menu.main_toolbar_menu, menu)
            }

            override fun onMenuItemSelected(menuItem: MenuItem): Boolean =
                if (menuItem.itemId == R.id.action_add) {
                    ConfigureActivity.openConfigure(this@MainActivity, true)
                    true
                } else {
                    false
                }
        }
    }

    private val scanKeyService: ScanKeyService by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        scanKeyService.registerCallback(mCallback, "250")
        super.onCreate(savedInstanceState)

        initNavManager()
        initBottomNavigation()

        addMenuProvider(menuProvider)

        lifecycleScope.launch { viewModel.uiEffectFlow.collect(::sideEffect) }
        lifecycleScope.launch { viewModel.uiStateFlow.collect(::render) }
    }

    private fun render(state: MainViewModel.UiState) {
        when (state) {
            is MainViewModel.UiState.BusinessSuccess -> {
                (getCurrentFragment() as? BusinessInfoFragment)?.handleBusinessInfo(state.businessModel)
            }
            is MainViewModel.UiState.MetadataUserSuccess->{
                (getCurrentFragment() as? BusinessInfoFragment)?.handleMetadataUserInfo(state.metadataUserModel)
            }
            else -> Unit
        }
    }

    private fun sideEffect(effect: MainViewModel.UiEffect) {
        when (effect) {
            is MainViewModel.UiEffect.ShowToast -> toast(effect.msg)
            is MainViewModel.UiEffect.ShowLoading -> showLoadingDialog()
            is MainViewModel.UiEffect.HideLoading -> hideLoadingDialog()
            is MainViewModel.UiEffect.ShowDeviceSuccess -> showTipDialog(content = effect.msg) {
                viewModel.setupTcpClient()
            }

            is MainViewModel.UiEffect.DialogEffect -> {
                val icon = when (effect) {
                    is MainViewModel.UiEffect.DialogEffect.Success -> com.yunchao.feature.base.R.drawable.ic_success_img
                    is MainViewModel.UiEffect.DialogEffect.Error -> com.yunchao.feature.base.R.drawable.ic_error_img
                    is MainViewModel.UiEffect.DialogEffect.Warning -> com.yunchao.feature.base.R.drawable.ic_warning_img
                }
                showTipDialog(icon = icon, content = effect.message)
            }
        }
    }

    private fun initNavManager() {
        navManager.setOnNavEvent { getCurrentFragment()?.navigateSafe(it) }
    }

    private fun initBottomNavigation() {
        // When using FragmentContainerView, NavController fragment can't be retrieved by using `findNavController()`
        // See https://stackoverflow.com/questions/59275009/fragmentcontainerview-using-findnavcontroller/59275182#59275182
        // See https://issuetracker.google.com/issues/142847973
        val navController = binding.navHostFragment.getFragment<NavHostFragment>().navController
        navController.addOnDestinationChangedListener(this)
        setSupportActionBar(binding.baseToolbar)

        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.peopleBusinessNavGraph, R.id.lockNavGraph
            )
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        binding.bottomNav.setupWithNavController(navController)
    }

    private fun getCurrentFragment(): Fragment? {
        val navHostFragment =
            supportFragmentManager.findFragmentById(R.id.navHostFragment)
        val currentFragment = navHostFragment?.childFragmentManager?.primaryNavigationFragment
        return currentFragment
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = binding.navHostFragment.getFragment<NavHostFragment>().navController
        return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onNavigateUp()
    }

    override fun onDestinationChanged(
        controller: NavController,
        destination: NavDestination,
        arguments: Bundle?
    ) {
        when (destination.label) {
            getString(com.yunchao.feature.base.R.string.功能区),
            getString(com.yunchao.feature.base.R.string.业务区) -> {
                binding.bottomNav.visibility = View.VISIBLE
            }

            else -> {
                binding.bottomNav.visibility = View.GONE
            }
        }
    }

    override fun onStart() {
        super.onStart()
        viewModel.openDevice()
    }

    override fun onStop() {
        super.onStop()
        viewModel.closeDevice()
    }

    override fun onDestroy() {
        scanKeyService.unregisterCallback(mCallback)
        super.onDestroy()
    }

    private val mCallback: IKeyEventCallback = object : IKeyEventCallback.Stub() {
        override fun onKeyDown(p0: Int) {
            (getCurrentFragment() as? BaseKeyEventFragment)?.onceScanLock()
        }

        override fun onKeyUp(p0: Int) {
            (getCurrentFragment() as? BaseKeyEventFragment)?.onStopScanLock()
        }

    }
}


